import inspect
from src.basedata.infrastructure.common import messagebus, unit_of_work
from src.basedata.application import handlers


def bootstrap(
        uow: unit_of_work.AbstractUnitOfWork=None,
        uow_factory=None
) -> messagebus.MessageBus:
    dependencies = {"uow": uow}
    dependencies_factories = {'uow': uow_factory}

    injected_command_handlers = {
        command_type: inject_dependencies(handler, dependencies, dependencies_factories)
        for command_type, handler in handlers.COMMAND_HANDLERS.items()
    }

    return messagebus.MessageBus(
        uow=uow,
        command_handlers=injected_command_handlers,
    )


def inject_dependencies(handler, dependencies, dependencies_factories):
    params = inspect.signature(handler).parameters
    deps = {
        name: dependency
        for name, dependency in dependencies.items()
        if name in params
    }

    def c(message):
        for name, dependency_factory in dependencies_factories.items():
            if name in deps.keys():
                deps[name] = dependency_factory()
        return handler(message, **deps)

    return c
    # return lambda message: handler(message, **deps)
